
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Helper;
using IRepository;
using Models;
using System.Linq;
using Models.Entity;
using MySql.Data.MySqlClient;
using Dapper;
using System.Data;
using System.Linq.Expressions;

namespace Repository
{
    /// <summary>
    /// 图片处理服务
    /// </summary>
    public class WeekCourseChangeRepository : IWeekCourseChangeRepository
    {
        DapperHelper<CWeekCourseChangeEntity> dbHelper = new DapperHelper<CWeekCourseChangeEntity>();
        DapperHelper<CClassesWeekCourseEntityView> dbHelper_ClassesWeekCourse = new DapperHelper<CClassesWeekCourseEntityView>();
        DapperHelper<CWeekCourseEntity> dbHelper_WeekCourse = new DapperHelper<CWeekCourseEntity>();

        DapperHelper<CTeacherEntity> dbHelper_tearch = new DapperHelper<CTeacherEntity>();


        IWeekCourseRepository _WeekCourseRepository;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="weekCourseRepository"></param>
        public WeekCourseChangeRepository(IWeekCourseRepository weekCourseRepository)
        {
            this._WeekCourseRepository = weekCourseRepository;
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="inEnt"></param>
        /// <returns></returns>
        public async Task<ResultObj<int>> Save(DtoSave<CWeekCourseChangeEntity> inEnt)
        {
            ResultObj<int> reObj = new ResultObj<int>();
            #region 格式化时间
            if (inEnt.saveFieldList == null) inEnt.saveFieldList = new List<string>();

            if (!string.IsNullOrEmpty(inEnt.data.changeDateStr1))
            {
                inEnt.data.change_date1 = DateTimeHelper.getDateLong(Convert.ToDateTime(inEnt.data.changeDateStr1));
                inEnt.saveFieldList.Add("change_date1");
            }

            if (!string.IsNullOrEmpty(inEnt.data.changeDateStr2))
            {
                inEnt.data.change_date2 = DateTimeHelper.getDateLong(Convert.ToDateTime(inEnt.data.changeDateStr2));
                inEnt.saveFieldList.Add("change_date2");
            }
            #endregion

            #region 验证时间

            var course1 = await dbHelper_WeekCourse.Single(x => x.week_course_id == inEnt.data.week_course_id1);
            if (course1.order_num % 10 != (int)DateTimeHelper.getDate(inEnt.data.change_date1).DayOfWeek)
            {
                reObj.success = false;
                reObj.msg = "课程1时间不是周" + (int)DateTimeHelper.getDate(inEnt.data.change_date1).DayOfWeek;
                return reObj;
            }

            var course2 = await dbHelper_WeekCourse.Single(x => x.week_course_id == inEnt.data.week_course_id2);
            if (course2.order_num % 10 != (int)DateTimeHelper.getDate(inEnt.data.change_date2).DayOfWeek)
            {
                reObj.success = false;
                reObj.msg = "课程2时间不是周" + (int)DateTimeHelper.getDate(inEnt.data.change_date2).DayOfWeek;
                return reObj;
            }

            #endregion

            if (inEnt.data.id == 0)
            {
                var makeResult = await MakeWeekCourseChange(inEnt.data);
                if (!makeResult.success)
                {
                    reObj.success = false;
                    reObj.msg = string.Join("\r\n", makeResult.dataList);
                    return reObj;
                }
            }
            else
            {
                reObj.success = false;
                reObj.msg = "换课不能修改，只有删除后再重新创建";
                return reObj;
            }

            reObj.success = reObj.data > 0;
            return reObj;
        }

        /// <summary>
        /// 生成调课记录,返回需调课记录
        /// </summary>
        /// <param name="inEnt"></param>
        /// <returns></returns>
        public async Task<ResultObj<string>> MakeWeekCourseChange(CWeekCourseChangeEntity inEnt)
        {
            ResultObj<string> resultObj = new ResultObj<string>();
            resultObj = await CheckWeekCourseChange(inEnt);
            if (!resultObj.success)
            {
                return resultObj;
            }

            List<CWeekCourseChangeEntity> saveList = new List<CWeekCourseChangeEntity>();

            IList<CClassesWeekCourseEntityView> classes1 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == inEnt.week_course_id1)).ToList();
            IList<CClassesWeekCourseEntityView> classes2 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == inEnt.week_course_id2)).ToList();
            inEnt.create_time = DateTimeHelper.getDateLong(DateTime.Now);


            int years = classes1.Min(x => x.years);
            int num = classes1.Min(x => x.num);
            int order_num1 = classes1.Min(x => x.order_num);
            int order_num2 = classes2.Min(x => x.order_num);

            #region 统计出，要交换的班级

            //两个都是大班课,或都是小班课
            if (classes1.Count == classes2.Count)
            {
                inEnt.id = await SequenceRepository.GetNextID<CWeekCourseChangeEntity>();
                saveList.Add(inEnt);
            }
            else if (classes1.Count > classes2.Count)
            {
                foreach (var item in classes1)
                {

                    var single1 = await dbHelper_ClassesWeekCourse.Single(x => x.order_num == order_num1 && x.classes_id == item.classes_id);
                    var single2 = await dbHelper_ClassesWeekCourse.Single(x => x.order_num == order_num2 && x.classes_id == item.classes_id);
                    saveList.Add(new CWeekCourseChangeEntity
                    {
                        id = await SequenceRepository.GetNextID<CWeekCourseChangeEntity>(),
                        week_course_id1 = single1.week_course_id,
                        week_course_id2 = single2.week_course_id,
                        change_date1 = inEnt.change_date1,
                        change_date2 = inEnt.change_date2,
                        create_time = inEnt.create_time
                    });
                }
            }
            else
            {
                foreach (var item in classes2)
                {

                    var single1 = await dbHelper_ClassesWeekCourse.Single(x => x.order_num == order_num1 && x.classes_id == item.classes_id);
                    var single2 = await dbHelper_ClassesWeekCourse.Single(x => x.order_num == order_num2 && x.classes_id == item.classes_id);
                    saveList.Add(new CWeekCourseChangeEntity
                    {
                        id = await SequenceRepository.GetNextID<CWeekCourseChangeEntity>(),
                        week_course_id1 = single1.week_course_id,
                        week_course_id2 = single2.week_course_id,
                        change_date1 = inEnt.change_date1,
                        change_date2 = inEnt.change_date2,
                        create_time = inEnt.create_time
                    });
                }
            }

            #endregion

            int opNum = await dbHelper.Saves(new DtoSave<List<CWeekCourseChangeEntity>>
            {
                data = saveList
            });

            if (opNum < 1)
            {
                resultObj.success = false;
                resultObj.msg = "保存失败";
            }
            else
            {
                resultObj.success = true;

            }
            return resultObj;
        }

        /// <summary>
        /// 检测调课记录,返回需调课记录
        /// </summary>
        /// <param name="inEnt"></param>
        /// <returns></returns>
        public async Task<ResultObj<string>> CheckWeekCourseChange(CWeekCourseChangeEntity inEnt)
        {
            ResultObj<string> reObj = new ResultObj<string>();
            try
            {
                #region 格式化时间

                if (!string.IsNullOrEmpty(inEnt.changeDateStr1))
                {
                    inEnt.change_date1 = DateTimeHelper.getDateLong(Convert.ToDateTime(inEnt.changeDateStr1));
                }

                if (!string.IsNullOrEmpty(inEnt.changeDateStr2))
                {
                    inEnt.change_date2 = DateTimeHelper.getDateLong(Convert.ToDateTime(inEnt.changeDateStr2));
                }
                #endregion

                #region 验证时间

                var course1 = await dbHelper_WeekCourse.Single(x => x.week_course_id == inEnt.week_course_id1);
                if (course1 != null && course1.order_num % 10 != (int)DateTimeHelper.getDate(inEnt.change_date1).DayOfWeek)
                {
                    throw new Exception("课程1时间不是周" + (int)DateTimeHelper.getDate(inEnt.change_date1).DayOfWeek);
                }

                var course2 = await dbHelper_WeekCourse.Single(x => x.week_course_id == inEnt.week_course_id2);
                if (course2 != null && course2.order_num % 10 != (int)DateTimeHelper.getDate(inEnt.change_date2).DayOfWeek)
                {
                    throw new Exception("课程2时间不是周" + (int)DateTimeHelper.getDate(inEnt.change_date2).DayOfWeek);
                }

                #endregion

                if (inEnt.week_course_id1 == inEnt.week_course_id2)
                {
                    throw new Exception("相同课程");
                }


                IEnumerable<CClassesWeekCourseEntityView> classes1 = await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == inEnt.week_course_id1);
                IEnumerable<CClassesWeekCourseEntityView> classes2 = await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == inEnt.week_course_id2);

                if (classes1.Count() == classes2.Count() && classes1.Count() > 0)
                {
                    var t1 = classes1.ToList()[0];
                    var t2 = classes2.ToList()[0];
                    reObj.dataList.Add($@"班级[{t1.classes_name}][{_WeekCourseRepository.Formart(t1.order_num)}-{t1.teacher_name}:{t1.course_name}]与班级[{t2.classes_name}][{_WeekCourseRepository.Formart(t2.order_num)}][{t2.teacher_name}:{t2.course_name}]交换");
                    reObj.success = true;
                    return reObj;
                }

                int order_num1 = classes1.Min(x => x.order_num);
                int order_num2 = classes2.Min(x => x.order_num);
                if (classes1.Count() > classes2.Count())
                {
                    foreach (var item in classes1)
                    {
                        //判断交换的老师，是否在该时间有课
                        var isExistList1 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.order_num == order_num2 && x.teacher_id == item.teacher_id)).ToList();
                        if (isExistList1.Count() > 0)
                        {
                            throw new Exception($"老师[{isExistList1[0].teacher_name}]在[{isExistList1[0].classes_name}]的[{_WeekCourseRepository.Formart(order_num2)}有课，]");
                        }
                        else
                        {
                            var c2 = await dbHelper_ClassesWeekCourse.Single(x => x.order_num == order_num2 && x.classes_id == item.classes_id);
                            reObj.dataList.Add($"班级[{item.classes_name}]第[{_WeekCourseRepository.Formart(item.order_num)}-{item.teacher_name}:{item.course_name}]与[{_WeekCourseRepository.Formart(order_num2)}-{c2.teacher_name}:{c2.course_name}]交换");
                        }
                    }
                }
                else
                {
                    foreach (var item in classes2)
                    {
                        //判断交换的老师，是否在该时间有课
                        var isExistList = (await dbHelper_ClassesWeekCourse.FindAll(x => x.order_num == order_num1 && x.teacher_id == item.teacher_id)).ToList();
                        if (isExistList.Count() > 0)
                        {
                            throw new Exception($"老师[{isExistList[0].teacher_name}]在[{isExistList[0].classes_name}]的[{_WeekCourseRepository.Formart(order_num1)}有课，]");
                        }
                        else
                        {
                            var c2 = await dbHelper_ClassesWeekCourse.Single(x => x.order_num == order_num1 && x.classes_id == item.classes_id);
                            reObj.dataList.Add($"班级[{item.classes_name}]第[{_WeekCourseRepository.Formart(item.order_num)}-{item.teacher_name}:{item.course_name}]节与[{_WeekCourseRepository.Formart(order_num1)}-{c2.teacher_name}:{c2.course_name}]交换");
                        }
                    }
                }
            }
            catch (System.Exception e)
            {
                reObj.success = false;
                reObj.msg = e.Message;
            }
            return reObj;
        }




        /// <summary>
        /// 删除,会删除相关的换课
        /// </summary>
        /// <param name="key">主键 ID</param>
        /// <returns></returns>
        public async Task<ResultObj<int>> Delete(int key)
        {
            ResultObj<int> reObj = new ResultObj<int>();
            var deleteEnt = await dbHelper.Single(x => x.id == key);
            reObj.data = await dbHelper.Delete(x => x.create_time == deleteEnt.create_time);
            reObj.success = reObj.data > 0;
            return reObj;
        }
        /// <summary>
        /// 直接，交换过程，用于调整课表
        /// </summary>
        /// <param name="inEnt"></param>
        /// <returns></returns>
        public async Task<ResultObj<string>> ChangeWeekCourse(DtoDo<List<KV>> inEnt)
        {
            ResultObj<string> reObj = new ResultObj<string>();


            if (inEnt == null || inEnt.Key == null || inEnt.Key.Count() != 2 || inEnt.Key.Count(x => string.IsNullOrEmpty(x.k) || string.IsNullOrEmpty(x.v)) > 0)
            {
                reObj.msg = "输入数据有误";
                reObj.success = false;
                return reObj;
            }
            var ent1 = inEnt.Key[0];
            var ent2 = inEnt.Key[1];
            var order_num1 = (Convert.ToInt32(ent1.v) % 10) * 10 + (Convert.ToInt32(ent1.v) / 10);
            var order_num2 = (Convert.ToInt32(ent2.v) % 10) * 10 + (Convert.ToInt32(ent2.v) / 10);
            var single1 = await dbHelper_ClassesWeekCourse.Single(x => x.classes_name == ent1.k && x.order_num == order_num1);
            var single2 = await dbHelper_ClassesWeekCourse.Single(x => x.classes_name == ent2.k && x.order_num == order_num2);
            List<int> changeIdList1 = new List<int>();
            List<int> changeIdList2 = new List<int>();

            Console.WriteLine($"order_num1={order_num1}");
            Console.WriteLine($"order_num2={order_num2}");

            List<CClassesWeekCourseEntityView> classesList1 = new List<CClassesWeekCourseEntityView>();
            List<CClassesWeekCourseEntityView> classesList2 = new List<CClassesWeekCourseEntityView>();
            if ((single1 == null && single2 == null) || single1 == single2)
            {
                reObj.msg = "输入数据有误";
                reObj.success = false;
                return reObj;
            }

            #region  如果有一个为空，找出合班的课，是否为空
            if (single1 == null || single2 == null)
            {
                if (single1 == null)
                {
                    classesList2 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == single2.week_course_id)).ToList();
                    foreach (var item in classesList2)
                    {
                        if (single2.classes_id != item.classes_id)
                        {
                            Console.WriteLine(item.classes_name);
                            single1 = await dbHelper_ClassesWeekCourse.Single(x => x.classes_name == item.classes_name && x.order_num == order_num1);
                            single2 = await dbHelper_ClassesWeekCourse.Single(x => x.classes_name == item.classes_name && x.order_num == order_num2);
                            break;
                        }
                    }
                }
                else //single2=null
                {
                    classesList1 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == single1.week_course_id)).ToList();
                    foreach (var item in classesList1)
                    {
                        if (single1.classes_id != item.classes_id)
                        {
                            Console.WriteLine(item.classes_name);
                            single1 = await dbHelper_ClassesWeekCourse.Single(x => x.classes_name == item.classes_name && x.order_num == order_num1);
                            single2 = await dbHelper_ClassesWeekCourse.Single(x => x.classes_name == item.classes_name && x.order_num == order_num2);
                            break;
                        }
                    }
                }
            }
            #endregion

            //单个为空
            if (single1 == null || single2 == null)
            {
                if (single1 == null)
                {
                    classesList2 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == single2.week_course_id)).ToList();

                    //检测老师是否有空,应该只有一个老师
                    reObj = await CheckTearcherClass(classesList2, order_num1);
                    if (!reObj.success) return reObj;


                    await dbHelper_WeekCourse.Update(new DtoSave<CWeekCourseEntity>
                    {
                        data = new CWeekCourseEntity { week_course_id = single2.week_course_id, order_num = order_num1 },
                        saveFieldListExp = (x => new object[] { x.order_num }),
                        whereListExp = (x => new object[] { x.week_course_id })
                    });
                }
                else //single2=null
                {

                    classesList1 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == single1.week_course_id)).ToList();

                    //检测老师是否有空,应该只有一个老师
                    reObj = await CheckTearcherClass(classesList1, order_num2);
                    if (!reObj.success) return reObj;


                    await dbHelper_WeekCourse.Update(new DtoSave<CWeekCourseEntity>
                    {
                        data = new CWeekCourseEntity { week_course_id = single1.week_course_id, order_num = order_num2 },
                        saveFieldListExp = (x => new object[] { x.order_num }),
                        whereListExp = (x => new object[] { x.week_course_id })
                    });
                }
            }
            else //全不为空
            {
                classesList1 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == single1.week_course_id)).ToList();
                classesList2 = (await dbHelper_ClassesWeekCourse.FindAll(x => x.week_course_id == single2.week_course_id)).ToList();
                Console.WriteLine($"1教室数{string.Join(',', classesList1.Select(x => x.classes_id))}");
                Console.WriteLine($"2教室数{string.Join(',', classesList2.Select(x => x.classes_id))}");
                
                //检测老师是否有空,应该只有一个老师
                reObj = await CheckTearcherClass(classesList2, order_num1);
                if (!reObj.success) return reObj;


                //检测老师是否有空
                reObj = await CheckTearcherClass(classesList1, order_num2);
                if (!reObj.success) return reObj;
                

                //如果有多个班级，则表示有多个对调
                foreach (var item in classesList1)
                {
                    var week_course_id = (await dbHelper_ClassesWeekCourse.Single(x => x.classes_id == item.classes_id && x.order_num == order_num2))?.week_course_id;

                    if (week_course_id.HasValue)
                    {
                        Console.WriteLine($"2教室week_course_id[{week_course_id}]");
                        changeIdList2.Add(week_course_id.Value);
                    }
                }
                foreach (var item in classesList2)
                {
                    var week_course_id = (await dbHelper_ClassesWeekCourse.Single(x => x.classes_id == item.classes_id && x.order_num == order_num1))?.week_course_id;
                    if (week_course_id.HasValue)
                    {
                        Console.WriteLine($"1教室week_course_id[{week_course_id}]");
                        changeIdList1.Add(week_course_id.Value);
                    }
                }

                foreach (var item in changeIdList1)
                {
                    await dbHelper_WeekCourse.Update(new DtoSave<CWeekCourseEntity>
                    {
                        data = new CWeekCourseEntity { week_course_id = item, order_num = order_num2 },
                        saveFieldListExp = (x => new object[] { x.order_num }),
                        whereListExp = (x => new object[] { x.week_course_id })
                    });
                }

                foreach (var item in changeIdList2)
                {
                    await dbHelper_WeekCourse.Update(new DtoSave<CWeekCourseEntity>
                    {
                        data = new CWeekCourseEntity { week_course_id = item, order_num = order_num1 },
                        saveFieldListExp = (x => new object[] { x.order_num }),
                        whereListExp = (x => new object[] { x.week_course_id })
                    });
                }
            }
            reObj.success = true;
            return reObj;
        }

        /// <summary>
        /// 检测老师是否可以排课
        /// </summary>
        /// <param name="classesList"></param>
        /// <param name="order_num"></param>
        /// <returns></returns>
        public async Task<ResultObj<string>> CheckTearcherClass(List<CClassesWeekCourseEntityView> classesList, int order_num)
        {
            ResultObj<string> reObj = new ResultObj<string>();
            foreach (var item in classesList)
            {
                if ((await dbHelper_tearch.Count($"teacher_id={item.teacher_id} and no_course like '%{order_num}%'")) > 0)
                {
                    reObj.msg = $"老师[{item.teacher_name}]配置了在[{order_num}]不排课";
                    reObj.success = false;
                    return reObj;
                }

                if ((await dbHelper_ClassesWeekCourse.Count(x => x.teacher_id == item.teacher_id && x.order_num == order_num)) > 0)
                {
                    reObj.msg = $"老师[{item.teacher_name}]在第[{order_num}]节课不空";
                    reObj.success = false;
                    return reObj;
                }
            }
            reObj.success = true;
            return reObj;
        }
    }
}
